package cn.net.Singleton;
/*本类用于测试单例设计模式 2 - 懒汉式--面试重点!!!*/
public class TestSingle2 {
    public static void main(String[] args) {
        ////通过类名调用getMySingle2()静态方法来创建对象
        MySingle2 single1 = MySingle2.getSingle2();
        MySingle2 single2 = MySingle2.getSingle2();
        System.out.println(single1==single2);//判断地址值是否相等true

    }
}
/*问题：共享资源single2，有多条语句操作共享资源，所以存在安全隐患
* 解决：方法一：同步代码块；加锁，其范围是操作共享资源的所有代码
* 方案二：同步方法：一个方法中所有代码均需被同步。
* 注意：锁对象不能为this，因为静态资源优先于this对象的加载。
* 锁对象可以使用外部Object创建好的唯一锁对象o，但注意设置为静态对象o
* 因为静态只能调用静态。
* */
//创建自定义的单例类程序
class MySingle2{
    //1.私有化构造方法,为了防止外部调用构造方法直接创建本类对象
    private MySingle2(){
        System.out.println("abc");
    }
    ////2.在类的内部创建好引用类型变量(延迟加载（懒加载）的思想)--注意私有化
    //修饰成static的,因为静态只能调用静态,getMySingle2()是静态方法
    private static MySingle2 single2;//定义引用类型变量【静态+私有化】；默认值为null
    //7.2.2同步代码块中使用static-唯一的锁对象
    static Object o = new Object();
    //3.对外提供公共的全局访问点;将方法修饰成同步方法
    //注意:使用static公共静态方法,为了方便后续可以通过类名直接调用
  synchronized    static public MySingle2 getSingle2() {
      /*注意:这里需要增加一个判断
        如果调用方法时single2的值为null,说明之前没有new过,保存的是默认值null
        这时才需要new对象,如果single2的值不为null,直接return single2即可*/
      synchronized (o) {//7.2可以将操作共享资源的多条语句放入同步代码块之中
          //synchronized (this) { //this不可以在静态区使用
          if (single2 == null) {//判断有无对象
              single2 = new MySingle2();//没有对象时才创建对象,并赋值给single2
          }
          return single2;//调用方法，需返回对象
      }

  }
}